/**
 * Copyright (c) 2019 xstgongyi.org
 * All rights reserved.
 */
package org.xstgongyi.eduaid.controller;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xstgongyi.eduaid.common.ControllerHelper;
import org.xstgongyi.eduaid.dataobject.UserDO;
import org.xstgongyi.eduaid.service.UserService;

/**
 * @author oldcrane<br/>
 * @created 2019-05-16
 */
@Controller
public class AuthController {

	@Autowired
	private HttpServletRequest request;

	@Autowired
	private UserService userService;

	@GetMapping("/login")
	public String loginPage(ModelMap map) {
		return "login";
	}

	// GET方式的logout，为jsp界面所用，暂时保留，准备废弃
	@Deprecated
	@GetMapping("/logout")
	public String logoutPage(ModelMap map) {
		Subject subject = SecurityUtils.getSubject();
		if (null != subject) {
			subject.logout();
		}
		return "redirect:/login";
	}

	@PostMapping("/logout")
	@ResponseBody
	public Map<String, Object> logout(ModelMap map) {
		Subject subject = SecurityUtils.getSubject();
		if (null != subject && subject.isAuthenticated()) {
			subject.logout();
			return ControllerHelper.successResponse(null, "用户已成功logout");
		} else {
			return ControllerHelper.errorResponse(401, "用户已logout或非法的token，无法执行logout");
		}
	}

	@PostMapping("/login")
	@ResponseBody
	public Map<String, Object> login(@RequestBody Map<String, Object> map) {
		String loginName = (String) map.get("loginName");
		String password = (String) map.get("password");
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(loginName, password);
		try {
			subject.login(token);

			// when success, assemble response
			// ZoneOffset offset = OffsetDateTime.now().getOffset();
			LocalDateTime now = LocalDateTime.now();
			// long epochSecond = now.toEpochSecond(offset);
			LocalDateTime expireTime = now.plusMinutes(30);
			Map<String, Object> resp = new HashMap<>();
			// resp.put("token", token.getUsername() + String.valueOf(epochSecond));
			String sessionId = (String) subject.getSession().getId();
			resp.put("token", sessionId);
			resp.put("expires", expireTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

			return ControllerHelper.successResponse(resp);

		} catch (AuthenticationException ex) {
			String message = "登录失败。请访问登录页面：" + request.getRequestURL();
			return ControllerHelper.errorResponse(401, message);
		}
	}

	@GetMapping("/token")
	@ResponseBody
	public Map<String, Object> refresh_token() {
		// 前后端分离的情况下，服务器端目前继续使用session。
		// 被调用时，检查session是否存在，如果是，则返回session_id。如果session不存在，返回身份校验失败。
		Subject subject = SecurityUtils.getSubject();
		if (subject.isAuthenticated()) {
			Map<String, Object> resp = new HashMap<>();
			String sessionId = (String) subject.getSession().getId();
			resp.put("token", sessionId);
			LocalDateTime now = LocalDateTime.now();
			LocalDateTime expireTime = now.plusMinutes(30);
			resp.put("expires", expireTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
			return ControllerHelper.successResponse(resp);
		} else {
			String message = "invalid token。请先登录：" + request.getRequestURL();
			return ControllerHelper.errorResponse(401, message);
		}
	}

	@GetMapping("/unauthorized")
	@ResponseBody
	public Map<String, Object> unauthorized(ModelMap map) {
		String url = request.getRequestURL().toString();
		String loginUrl = StringUtils.replace(url, "/unauthorized", "/login");
		String message = "登录失败。请访问登录页面：" + loginUrl;
		return ControllerHelper.errorResponse(401, message);
	}

	@GetMapping("/userinfo")
	@ResponseBody
	public Map<String, Object> userInfo(ModelMap map) {
		Subject subject = SecurityUtils.getSubject();
		String loginName = (String) subject.getPrincipal();
		UserDO user = userService.getByLoginName(loginName);
		if (null != user) {
			Map<String, Object> resp = new HashMap<>();
			resp.put("showName", user.getShowName());
			resp.put("loginName", user.getLoginName());
			return ControllerHelper.successResponse(resp);
		} else {
			return ControllerHelper.errorResponse(404, "Cannot find user. Please login first.");
		}
	}

}
